/*
 * Copyright 2017 the original author or authors.
 *
 */

package com.ivo.util;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <h1>异常工具类</h1>
 * <p>
 * content
 * </p>
 * <b>Note:</b>
 *
 * @author nexf
 * @since 2015/10/2 13:46
 */
public class ExceptionUtil extends ExceptionUtils {

  private static final Logger logger = LoggerFactory.getLogger(ExceptionUtil.class);

  /**
   * 将CheckedException转换为UncheckedException.
   *
   * @param e 目标异常
   * @return 转换后的运行时异常
   */
  public static RuntimeException unchecked(Throwable e) {
    if (e instanceof RuntimeException) {
      return (RuntimeException) e;
    } else {
      return new RuntimeException(e);
    }
  }

  /**
   * 把异常记录到日志
   *
   * @param msg 消息
   * @param args 参数
   */
  public static void warn(String msg, Object... args) {
    logger.warn(msg, args);
  }


  /**
   * 把异常记录到日志
   *
   * @param e 目标异常
   */
  public static void error(Throwable e) {
    error(e, getMessage(e));
  }

  /**
   * 把异常记录到日志
   *
   * @param e 目标异常
   * @param msg 消息
   */
  public static void error(Throwable e, String msg) {
    logger.error(msg, e);
  }

  /**
   * 判断异常是否由某些底层的异常引起.
   *
   * @param e 目标异常
   * @param causeExceptionClasses 底层异常数组
   * @return 是/否
   */
  @SafeVarargs
  public static boolean isCausedBy(Exception e,
      Class<? extends Exception>... causeExceptionClasses) {
    if (causeExceptionClasses == null || causeExceptionClasses.length == 0) {
      return false;
    }
    Throwable cause = e;
    while (cause != null) {
      for (Class<? extends Exception> causeClass : causeExceptionClasses) {
        if (causeClass != null && causeClass.isInstance(cause)) {
          return true;
        }
      }
      cause = cause.getCause();
    }
    return false;
  }

  /**
   * 获取真正异常的原因
   *
   * @param e 异常
   * @return 指定异常类型实例
   */
  public static Throwable getCaused(Throwable e) {
    return getCaused(e, null);
  }

  /**
   * 获取真正异常的原因
   *
   * @param e 异常
   * @param exception 异常类型
   * @return 指定异常类型实例
   */
  public static Throwable getCaused(Throwable e, Class<? extends Exception> exception) {
    Throwable cause = e;
    while (cause != null) {
      if (exception != null && exception.isInstance(cause)) {
        return cause;
      }
      cause = cause.getCause();
    }
    return e;
  }

}
